home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Tcl / Modes / HTML and CSS Modes / htmlProcs.tcl < prev    next >
Encoding:
Text File  |  2001-01-12  |  17.7 KB  |  605 lines

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  HTML mode - tools for editing HTML documents
  4.  # 
  5.  #  FILE: "htmlProcs.tcl"
  6.  #                                    created: 99-07-20 18.20.31 
  7.  #                                last update: 01-01-09 19.24.45 
  8.  #  Author: Johan Linde
  9.  #  E-mail: <alpha_www_tools@go.to>
  10.  #     www: <http://go.to/alpha_www_tools>
  11.  #  
  12.  # Version: 3.0
  13.  # 
  14.  # Copyright 1996-2001 by Johan Linde
  15.  #  
  16.  # This program is free software; you can redistribute it and/or modify
  17.  # it under the terms of the GNU General Public License as published by
  18.  # the Free Software Foundation; either version 2 of the License, or
  19.  # (at your option) any later version.
  20.  # 
  21.  # This program is distributed in the hope that it will be useful,
  22.  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  # GNU General Public License for more details.
  25.  # 
  26.  # You should have received a copy of the GNU General Public License
  27.  # along with this program; if not, write to the Free Software
  28.  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  # 
  30.  # ###################################################################
  31.  ##
  32.  
  33.  
  34. # Checks if the current position is inside the container ELEM.
  35. proc html::IsInContainer {elem {pos ""}} {
  36.     set exp1 "<${elem}(\[ \t\r\n\]+\[^<>\]*>|>)"
  37.     set exp2 "</${elem}>"
  38.     return [html::_IsInContainer $pos $exp1 $exp2]
  39. }
  40.  
  41. proc html::IsInCommentContainer {elem {pos ""}} {
  42.     set exp1 "<!--\[ \t\r\n\]*#${elem}\[ \t\r\n\]*-->"
  43.     set exp2 "<!--\[ \t\r\n\]*/#${elem}\[ \t\r\n\]*-->"
  44.     return [html::_IsInContainer $pos $exp1 $exp2]
  45. }
  46.  
  47. proc html::_IsInContainer {pos exp1 exp2} {
  48.     if {$pos == ""} {set pos [getPos]}
  49.     if {![catch {search -s -f 0 -r 1 -i 1 -m 0 $exp1 $pos} res1] && [pos::compare $pos > [lindex $res1 1]] &&
  50.     ([catch {search -s -f 0 -r 1 -i 1 -m 0 $exp2 $pos} res2] || 
  51.     [pos::compare [lindex $res1 0] > [lindex $res2 0]])} {
  52.         return 1
  53.     }
  54.     return 0    
  55. }
  56.  
  57. proc html::IsThereAHomePage {} {
  58.     global HTMLmodeVars    
  59.     if {![llength $HTMLmodeVars(homePages)]} {
  60.         alertnote "You must set a home page folder."
  61.         html::HomePages
  62.     }
  63.     return [llength $HTMLmodeVars(homePages)]
  64. }
  65.  
  66. proc html::WhichHomePage {msg} {
  67.     global HTMLmodeVars
  68.     foreach hp $HTMLmodeVars(homePages) {
  69.         lappend hplist "[lindex $hp 1][lindex $hp 2]"
  70.     }
  71.     if {[catch {listpick -p "Select home page to $msg." $hplist} hp] || ![string length $hp]} {error ""}
  72.     set home [lindex $HTMLmodeVars(homePages) [lsearch -exact $hplist $hp]]
  73.     if {![file exists [lindex $home 0]] || ![file isdirectory [lindex $home 0]]} {
  74.         alertnote "Can't find the folder for [lindex $home 1][lindex $home 2]"
  75.         error ""
  76.     }
  77.     return $home
  78. }
  79.  
  80. # Determines the path to the home page folder corresponding to path.
  81. # If none, return empty string.
  82. proc html::WhichHomeFolder {path} {
  83.     set p [html::BASEfromPath $path]
  84.     if {[lindex $p 0] != "file:///"} {return [list [lindex $p 3] [lindex $p 0] [lindex $p 1]]}
  85.     return ""
  86. }
  87.  
  88.  
  89. # Determines the path to the include folder corresponding to path.
  90. # If none, return empty string.
  91. proc html::WhichInclFolder {path} {
  92.     return [lindex [html::BASEfromPath $path] 5]
  93. }
  94.  
  95. # Escapes certain characters in URLs.
  96. proc html::URLescape {str {slash 0}} {
  97.     set hexa {0 1 2 3 4 5 6 7 8 9 A B C D E F}
  98.     set nstr ""
  99.     set exp "\[\001- \177-ˇ%<>\"#\?=&;|\\{\\}\\`^"
  100.     if {$slash} {append exp "/"}
  101.     append exp "\]"
  102.     while {[regexp -indices $exp $str c]} {
  103.         set asc [text::Ascii [string index $str [lindex $c 0]]]
  104.         append nstr [string range $str 0 [expr {[lindex $c 0] - 1}]]
  105.         append nstr % [lindex $hexa [expr {$asc / 16}]] [lindex $hexa [expr {$asc % 16}]]
  106.         set str [string range $str [expr {[lindex $c 1] + 1}] end]
  107.     }
  108.     return "$nstr$str"
  109. }
  110.  
  111. proc html::URLescape2 {str} {
  112.     set url ""
  113.     regexp {[^#]*} $str url
  114.     set anchor [string range $str [string length $url] end]
  115.     return "[html::URLescape $url]$anchor"
  116. }
  117.  
  118. # Translate escaped characters in URLs.
  119. proc html::URLunEscape {str} {
  120.     set hexa {0 1 2 3 4 5 6 7 8 9 A B C D E F}
  121.     set nstr ""
  122.     while {[regexp -indices {%[0-9A-F][0-9A-F]} $str hex]} {
  123.         append nstr [string range $str 0 [expr {[lindex $hex 0] - 1}]]
  124.         append nstr [text::Ascii [expr {16 * [lsearch $hexa [string index $str [expr {[lindex $hex 0] + 1}]]] \
  125.         + [lsearch $hexa [string index $str [expr {[lindex $hex 0] + 2}]]]}] 1]
  126.         set str [string range $str [expr {[lindex $hex 1] + 1}] end]
  127.     }
  128.     return "$nstr$str"
  129. }
  130.  
  131.  
  132. # Puts up a window with error text.
  133. proc html::ErrorWindow {errHeader errText {cancelButton 0}} {
  134.     
  135.     set errbox "-t {$errHeader} 100 10 400 25"
  136.     set hpos 35
  137.     foreach err $errText {
  138.         if {[string length $err] < 55} {
  139.             lappend errbox -t $err 10 $hpos 450 [expr {$hpos + 15}]
  140.             incr hpos 20
  141.         } else {
  142.             lappend errbox -t $err 10 $hpos 450 [expr {$hpos + 30}]
  143.             incr hpos 35
  144.         }
  145.     }
  146.     if {$cancelButton} {
  147.         lappend errbox -b Cancel 105 [expr {$hpos + 20}] 170 [expr {$hpos + 40}]
  148.     }
  149.     
  150.     set val [eval [concat dialog -w 480 -h [expr {$hpos + 50}] \
  151.     -b OK 20 [expr {$hpos + 20}] 85 [expr {$hpos + 40}] $errbox]]
  152.     return [lindex $val 0]
  153. }
  154.  
  155.  
  156. proc html::IsInteger {str} {
  157.     return [regexp {^-?[0-9]+$} [string trim $str]]
  158. }
  159.  
  160. # Checks to see if the current window is empty, except for whitespace.
  161. proc html::IsEmptyFile {} {
  162.     return [catch {search -s -f 1 -r 1 {[^ \t\r\n]+} [minPos]}]
  163. }
  164.  
  165.  
  166. # Quoting of strings for meta tags.
  167. proc html::Quote {str} {
  168.     regsub -all "#" $str {#;} str
  169.     regsub -all "\"" $str {#qt;} str
  170.     regsub -all "<" $str {#lt;} str
  171.     regsub -all ">" $str {#gt;} str
  172.     return $str
  173. }
  174.  
  175. proc html::UnQuote {str} {
  176.     regsub -all {#qt;} $str "\"" str
  177.     regsub -all {#lt;} $str "<" str
  178.     regsub -all {#gt;} $str ">" str
  179.     regsub -all {#;} $str "#" str
  180.     return $str
  181. }
  182.  
  183. proc html::FindLargestMatch {ll pat {u ""} {sort 0}} {
  184.     global listPickIfMultCmps
  185.     upvar $ll l
  186.     set matches ""
  187.     foreach p $l {
  188.         if {[string match $pat* $p]} {lappend matches $p}
  189.     }
  190.     if {$sort} {set matches [lsort $matches]}
  191.     if {[llength $matches] > 1 && [info exists listPickIfMultCmps] && $listPickIfMultCmps} {
  192.         set matches [list [listpick -p "Pick a completion" $matches]]
  193.         if {$matches == ""} {error ""}
  194.     }
  195.     if {$u != ""} {
  196.         upvar $u unique
  197.         set unique [expr {[llength $matches] == 1}]
  198.     }
  199.     return [largestPrefix $matches]
  200. }
  201.  
  202. # Find the version number of a program.
  203. # Returns 0 if any problem.
  204. proc html::GetVersion {sig} {
  205.     if {[catch {app::ensureRunning $sig}]} {
  206.         return 0
  207.     }
  208.     set vers [AEBuild -r '$sig' core getd ---- "obj{want:type('prop'),from:null(),form:'prop',seld:type('vers')}"]
  209.     if {[regexp {vers\(«([0-9]+)} $vers dum vers]} {
  210.         return [string trimleft [string range $vers 0 1].[string range $vers 2 3] 0]
  211.     }
  212.     return 0
  213. }
  214.  
  215. proc html::CommentStrings {} {
  216.     if {[html::IsInContainer SCRIPT] || [html::IsInContainer STYLE]} {
  217.         return [list "/* " " */"]
  218.     } else {
  219.         return [list "<!-- " " -->"]
  220.     }
  221. }
  222.  
  223. proc html::URLregexp {} {
  224.     set exp "([join [html::GetURLAttrs] |])"
  225.     regsub -all {=} $exp "" exp
  226.     append exp {[ \t\n\r]*=[ \t\n\r]*("[^">]+"|'[^'>]+'|[^ \t\n\r"'>]+)}    
  227.     return $exp
  228. }
  229.  
  230. # Create a string for URL mapping in Big Brother.
  231. proc html::URLmap {} {
  232.     global HTMLmodeVars
  233.     set urlmap {}
  234.     foreach hp $HTMLmodeVars(homePages) {
  235.         set fld "[html::URLescape [lindex $hp 0] 1]/"
  236.         regsub -all ":" $fld "/" fld
  237.         set url [html::URLescape "[lindex $hp 1][lindex $hp 2]"]
  238.         lappend urlmap "Msta:“$url”, Mend:“file:///$fld”"
  239.         append urlmap ","
  240.     }
  241.     set urlmap [string trimright $urlmap ","]
  242.     return $urlmap
  243. }
  244.  
  245. # Makes a line for browser error window.
  246. proc html::BrwsErr {fil l lnum ln text path} {
  247.     return "$fil[format "%$l\s" ""]; Line $lnum:[format "%$ln\s" ""]$text\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$path\r"
  248. }
  249.  
  250. proc html::SetWin {} {
  251.     insertColorEscape [minPos] 1
  252.     insertColorEscape [nextLineStart [nextLineStart [minPos]]] 0
  253.     select [nextLineStart [nextLineStart [minPos]]] [nextLineStart [nextLineStart [nextLineStart [minPos]]]]
  254.     setWinInfo dirty 0
  255.     setWinInfo read-only 1
  256.     scrollUpLine; scrollUpLine
  257.     refresh
  258. }
  259.     
  260. proc html::IsTextFile {fil cmd} {
  261.     if {[file isdirectory $fil] || [getFileType $fil] != "TEXT"} {
  262.         $cmd "[file tail $fil] is not a text file."
  263.         return 0
  264.     }
  265.     return 1
  266. }
  267.  
  268. proc html::AllSaved {msg} {
  269.     set dirty 0
  270.     foreach w [winNames -f] {
  271.         if {![catch {getWinInfo -w $w arr}] && $arr(dirty)} {set dirty 1; break}
  272.     }
  273.     if {$dirty} {
  274.         set yn [eval [concat askyesno $msg]]
  275.         if {$yn == "yes"} {saveAll}
  276.         return $yn
  277.     }
  278.     return yes
  279. }
  280.  
  281. # Determines in which home page folder a URL points to.
  282. # If none, return empty string.
  283. proc html::InWhichHomePage {url} {
  284.     global HTMLmodeVars
  285.     foreach p $HTMLmodeVars(homePages) {
  286.         if {[string match "[lindex $p 1][lindex $p 2]*" $url]} {return [lindex $p 0]}
  287.     }
  288.     return ""
  289. }
  290.  
  291. # Asks for a folder and checks that it is not an alias.
  292. proc html::GetDir {prompt} {
  293.     while {1} {
  294.         if {[file isdirectory [set folder [get_directory -p $prompt]]]} {
  295.             break
  296.         } else {
  297.             alertnote "Sorry! Cannot resolve aliases."
  298.         }
  299.     }
  300.     return $folder
  301. }
  302.  
  303.  
  304. # Returns a list of all attributes used in any HTML element.
  305. proc html::GetAllAttrs {} {
  306.     global html::ElemAttrOptional html::ElemAttrRequired
  307.     
  308.     foreach elem [array names html::ElemAttrOptional] {
  309.         if {[info exists html::ElemAttrRequired($elem)]} {
  310.             append allHTMLattrs " " [set html::ElemAttrRequired($elem)]
  311.         }
  312.         append allHTMLattrs " " [set html::ElemAttrOptional($elem)]
  313.     }
  314.     return $allHTMLattrs
  315. }
  316.  
  317.  
  318. # Snatch the current selection into htmlCurSel, set flag whether there is one
  319. proc html::GetSel {} {
  320.     global htmlCurSel htmlIsSel
  321.     set htmlCurSel [string trim [getSelect]]
  322.     set htmlIsSel [string length $htmlCurSel]
  323. }
  324.  
  325. proc html::AdditionsExists {} {
  326.     global html::PrefsFolder
  327.     return [expr {![catch {glob -dir [file join ${html::PrefsFolder} "New elements"] *}] || \
  328.       ![catch {glob -dir [file join ${html::PrefsFolder} "Modified elements"] *}]}]
  329. }
  330.  
  331. proc html::NewElementsExists {} {
  332.     global html::PrefsFolder
  333.     return [expr {![catch {glob -dir [file join ${html::PrefsFolder} "New elements"] *}]}]
  334. }
  335.  
  336. proc html::FrontWindowPath {} {
  337.     global tcl_platform
  338.     set w [lindex [winNames -f] 0]
  339.     if {$tcl_platform(platform) == "windows"} {
  340.         regsub -all {\\} $w / w
  341.     }
  342.     return $w
  343. }
  344.  
  345. proc html::StrippedFrontWindowPath {} {
  346.     return [stripNameCount [html::FrontWindowPath]]
  347. }
  348.  
  349. proc html::AllWindowPaths {} {
  350.     global tcl_platform
  351.     set w [winNames -f]
  352.     if {$tcl_platform(platform) == "windows"} {
  353.         regsub -all {\\} $w / w
  354.     }
  355.     return $w
  356. }
  357.  
  358. proc html::CRcharacter {} {
  359.     if {![catch {search -s -f 1 -m 0 -i 0 -r 0 "\r" [minPos]}]} {return "\r"}
  360.     if {![catch {search -s -f 1 -m 0 -i 0 -r 0 "\n" [minPos]}]} {return "\n"}
  361.     return "\r"
  362. }
  363.  
  364. # patch until ISO package is updated.
  365. proc html::ISOtime {} {
  366.     global html::TimeZone
  367.     set tid [mtime [now] iso]
  368.     if {[regexp {Z$} $tid]} {
  369.         if {![info exists html::TimeZone]} {
  370.             if {[catch {aebuild::result 'MACS' syso "GMT "} gmt]} {
  371.                 set html::TimeZone Z
  372.             } else {
  373.                 set html::TimeZone [format "%.2u" [expr {abs($gmt)/3600}]]:[format "%.2u" [expr {(abs($gmt) % 3600)/60}]]
  374.                 if {$gmt < 0} {
  375.                     set html::TimeZone "-${html::TimeZone}"
  376.                 } else {
  377.                     set html::TimeZone "+${html::TimeZone}"
  378.                 }
  379.             }
  380.         }
  381.         regsub "Z$" $tid ${html::TimeZone} tid
  382.     }
  383.     return $tid
  384. }
  385.  
  386. proc html::FindFirstOccurance {exp pos {dir 1}} {
  387.     while {![catch {search -s -f $dir -r 1 -i 1 -m 0 $exp $pos} res] && 
  388.     ![catch {search -s -f 0 -r 1 -i 1 -m 0 "<!--" [lindex $res 0]} res1] &&
  389.     ![catch {search -s -f 1 -r 1 -i 1 -m 0 -- "-->" [lindex $res1 1]} res2] && [pos::compare [lindex $res2 1] > [lindex $res 1]]} {
  390.         if {$dir} {
  391.             set pos [lindex $res2 1]
  392.         } else {
  393.             set pos [lindex $res1 0]
  394.         }
  395.     }
  396.     if {![catch {search -s -f $dir -r 1 -i 1 -m 0 $exp $pos} res]} {
  397.         return $res
  398.     }
  399.     error "Not found."
  400. }
  401.  
  402. #===============================================================================
  403. # The following 5 procs are extracted from html::TidyUp2. They are hardcoded
  404. # into html::TidyUp2 for efficiency reasons
  405. #===============================================================================
  406.  
  407. proc html::prepareForBreaking {wholeTag} {
  408.     set w ""
  409.     # To avoid line breaks inside attributes
  410.     while {[regexp -indices {=[ \t\r\n]*(\"[^ \"]* [^\"]*\"|'[^ ']* [^']*')} $wholeTag i]} {
  411.         append w [string range $wholeTag 0 [expr {[lindex $i 0] - 1}]]
  412.         regsub -all "\[ \t\r\n\]+" [string range $wholeTag [lindex $i 0] [lindex $i 1]] "" w1
  413.         append w $w1
  414.         set wholeTag [string range $wholeTag [expr {[lindex $i 1] + 1}] end]
  415.     }
  416.     set wholeTag $w$wholeTag
  417.     return $wholeTag
  418. }
  419.  
  420. proc html::BreakIntoLines {tmp ind} {
  421.     set crChar [html::CRcharacter]
  422.     regsub -all "\[ \t\]*$crChar\[ \t\]*" [string trim $tmp] " " tmp
  423.     set tmp [string trimright [breakIntoLines $tmp]]
  424.     regsub -all "" $tmp " " tmp
  425.     regsub -all "\r" $tmp "\r$ind" tmp
  426.     return $tmp
  427. }
  428.  
  429. proc html::indentCR {args} {
  430.     global html::ElemLayout
  431.     foreach c $args {
  432.         upvar crBef$c crBef$c crAft$c crAft$c crBef/$c crBef/$c crAft/$c crAft/$c
  433.         upvar blBef$c blBef$c blAft$c blAft$c blBef/$c blBef/$c blAft/$c blAft/$c
  434.         set crBef$c 0; set crAft$c 0; set crBef/$c 0; set crAft/$c 0
  435.         set blBef$c 0; set blAft$c 0; set blBef/$c 0; set blAft/$c 0
  436.         switch [set html::ElemLayout($c)] {
  437.             open00 -
  438.             nocr {}
  439.             open01 {set crAft$c 1}
  440.             open10 {set crBef$c 1}
  441.             open11 {set crBef$c 1; set crAft$c 1}
  442.             cr0 {set crBef$c 1; set crAft/$c 1}
  443.             cr1 {set blBef$c 1; set blAft/$c 1}
  444.             cr2 {set blBef$c 1; set crBef/$c 1; set blAft/$c 1; set crAft$c 1}
  445.         }
  446.     }
  447. }
  448.  
  449. proc html::crBefore {blBef crBef t ind c cu new} {
  450.     upvar $t text $c cr $cu curr
  451.     if {$blBef || $crBef} {
  452.         if {![is::Whitespace $curr]} {set cr 0; append text $ind}
  453.         append text [html::BreakIntoLines $curr $ind]
  454.         if {$cr == 1 && $blBef} {append text $ind}
  455.         if {$cr == 0} {
  456.             append text \r
  457.             incr cr
  458.             if {$cr == 1 && $blBef} {append text \r; incr cr}
  459.         }
  460.         if {$blBef && $cr < 2} {append text \r}
  461.         set curr $new
  462.     } else {
  463.         append curr $new
  464.     }
  465. }
  466.  
  467. proc html::crAfter {blAft crAft t i c cu closing indent} {
  468.     upvar $t text $c cr $i ind $cu curr
  469.     set cr 0
  470.     if {$blAft || $crAft} {
  471.         if {$closing && $indent} {
  472.             set ind [string range $ind 1 end]
  473.         }
  474.         if {![is::Whitespace $curr]} {append text $ind}
  475.         append text [html::BreakIntoLines $curr $ind]
  476.         if {$indent && !$closing} {append ind \t}
  477.         append text \r
  478.         incr cr
  479.         if {$blAft} {
  480.             append text $ind
  481.             append text \r
  482.             incr cr
  483.         }
  484.         set curr ""
  485.     }
  486. }
  487.  
  488. proc html::elecInsertion {text} {
  489.     upvar $text t
  490.     HTML::indentLine
  491.     if {[html::IndentShouldBeAdjusted]} {regsub -all  "\r" $t "\r\t" t}
  492.     if {[pos::compare [set p [text::firstNonWsLinePos [getPos]]] > [getPos]]} {goto $p}
  493.     elec::Insertion $t
  494. }
  495.  
  496. proc html::SaveBeforeSending {path} {
  497.     global HTMLmodeVars
  498.     if {[info exists HTMLmodeVars(saveWithoutAsking)] && $HTMLmodeVars(saveWithoutAsking)} {
  499.         save 
  500.     } else {
  501.         set ask [dialog -w 300 -h 130 -t "Save '[file tail $path]'?" 10 10 240 30 \
  502.           -c "Always save without asking when" 0 10 40 250 58 \
  503.           -t "sending a window to the browser." 25 60 290 80 \
  504.           -b Yes 20 100 85 120 \
  505.           -b No 110 100 175 120 -b Cancel 200 100 265 120]
  506.         if {[lindex $ask 3]} {error "Cancel"}
  507.         if {[lindex $ask 0]} {
  508.             set HTMLmodeVars(saveWithoutAsking) 1
  509.             prefs::modifiedModeVar saveWithoutAsking HTML
  510.         }
  511.         if {[lindex $ask 1]} {save}
  512.     }
  513. }
  514.  
  515. #===============================================================================
  516. # ◊◊◊◊ Help ◊◊◊◊ #
  517. #===============================================================================
  518.  
  519. # opens the manual in the browser.
  520. proc html::Help {} {
  521.     global HOME HTMLmodeVars browserSig
  522.     switch $HTMLmodeVars(manualStartPage) {
  523.         0 {set start HTMLmanual.html}
  524.         1 {set start [file join text TableOfContents.html]}
  525.         2 {set start [file join text HTMLmanualFrames.html]}
  526.     }
  527.     set path [file join $HTMLmodeVars(manualFolder) $start]
  528.     if {![file exists $path]} {
  529.         if {![catch {html::GetDir "Locate manual"} folder]} {
  530.             set path [file join $folder $start]
  531.             if {![file exists $path]} {
  532.                 alertnote "Folder doesn't contain the HTML manual."
  533.                 return
  534.             }
  535.             set HTMLmodeVars(manualFolder) $folder
  536.             prefs::modifiedModeVar manualFolder HTML
  537.         } else {
  538.             return
  539.         }
  540.     }
  541.     htmlSendWindow $path
  542.     if {!$HTMLmodeVars(browseInForeground)} {switchTo '$browserSig'}
  543. }
  544.  
  545. #===============================================================================
  546. # ◊◊◊◊ Send file to browser ◊◊◊◊ #
  547. #===============================================================================
  548.  
  549. proc htmlSendWindow {{path ""} {url 0}} {
  550.     global HTMLmodeVars browserSig tcl_platform
  551.  
  552.     if {$path == ""} {
  553.         set path [html::StrippedFrontWindowPath]
  554.  
  555.         if {[winDirty]} {
  556.             html::SaveBeforeSending $path
  557.             if {![file exists $path]} {
  558.                 alertnote "Can't send window to browser."
  559.                 return
  560.             }
  561.         }
  562.         # Get path again, in case it was Untitled before.
  563.         set path [html::StrippedFrontWindowPath]
  564.     }
  565.     if {$url} {set path [join [lrange [html::BASEfromPath $path] 0 2] ""]}
  566.     if {$tcl_platform(platform) == "macintosh"} {
  567.         if {![info exists browserSig] && [catch {getFileSig [icGetPref -t 1 Helper•http]} browserSig]} {set browserSig MOSS}
  568.         if {[catch {app::launchBack $browserSig}]} {
  569.             app::getSig "Please locate your web browser" browserSig
  570.             app::launchBack $browserSig
  571.         }
  572.         if {$url} {
  573.             AEBuild '$browserSig' WWW! OURL "----" "“$path”" FLGS 1
  574.         } else {
  575.             # MSIE opens the file in a new window unless an open URL event is used.
  576.             # Cyberdog opens the text file unless an open URL event is used.
  577.             if {$browserSig == "MSIE" || $browserSig == "dogz" || $browserSig == "iCAB"} {
  578.                 set path [html::URLescape $path 1]
  579.                 regsub -all : $path / path
  580.                 set flgs ""
  581.                 if {$browserSig == "MSIE"} {set flgs "FLGS 1"}
  582.                 eval AEBuild '$browserSig' WWW! OURL "----" "“file:///$path”" $flgs
  583.             } else {
  584.                 sendOpenEvent noReply '$browserSig' $path
  585.             }
  586.         }
  587.     } else {
  588.         if {![file exists $browserSig]} {
  589.             set browserSig [getfile "Please locate your web browser"]
  590.         }
  591.         if {$tcl_platform(platform) == "windows"} {
  592.             exec $browserSig $path &
  593.         }
  594.         if {$tcl_platform(platform) == "unix"} {
  595.             if {$url} {
  596.                 exec $browserSig -remote openURL($path) &
  597.             } else {
  598.                 set path [html::URLescape $path]
  599.                 exec $browserSig -remote openURL(file://$path) &
  600.             }
  601.         }
  602.     }
  603.     if {$HTMLmodeVars(browseInForeground)} {switchTo '$browserSig'}
  604. }
  605.